/*
 * libSOCKET.c
 *
 *  Created on: 30/12/2011
 *      Author: utn_so
 */

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>

int32_t crearServidor(char* IP, char* puerto) {
	//cargo datos del servidor
	struct sockaddr_in *local_address;
	local_address->sin_family = AF_INET;
	local_address->sin_addr.s_addr = INADDR_ANY;
	local_address->sin_port = htons(5300);

	// cargo datos del cliente
	struct sockaddr_in *remote_address;
	remote_address->sin_family = AF_INET;
	remote_address->sin_addr.s_addr = inet_addr(IP);
	remote_address->sin_port = htons(atoi(puerto));

	int32_t descriptor = socket(AF_INET, SOCK_STREAM, 0);
	if (descriptor < 0) {
		perror("socket()");
		return -1;
	}
	int32_t rc = bind(descriptor, local_address, sizeof(local_address));
	if (rc < 0) {
		perror("bind");
		return -1;
	}
	return descriptor;
}

int32_t crearCliente(char* IP, char* puerto) {

//cargo datos a donde enviaré
	struct sockaddr_in *remote_address;
	remote_address->sin_family = AF_INET;
	remote_address->sin_addr.s_addr = inet_addr(IP);
	remote_address->sin_port = htons(atoi(puerto));

	int32_t descriptor = socket(AF_INET, SOCK_STREAM, 0);
	if (descriptor < 0) {
		perror("socket()");
		return -1;
	}
	int32_t rc;
	while (rc = connect(descriptor, remote_address, sizeof(uint64_t)))
		;
	return descriptor;

}

void cerrarConexionSocket(int32_t descriptor) {
	close(descriptor);
}

int32_t aceptarConexion(uint32_t descriptor, char* IP, char* puerto) {

	struct sockaddr_in *remote_address;
	remote_address->sin_family = AF_INET;
	remote_address->sin_addr.s_addr = inet_addr(IP);
	remote_address->sin_port = htons(atoi(puerto));
	int32_t cliente = accept(descriptor, &remote_address,
			sizeof(struct sockaddr_in));
	if (cliente < 0) {
		perror("accept");
		return -1;
	}
	return cliente;
}

void enviarPaquete(int32_t descriptor, char* paquete) {
	uint8_t enviado = 0;
	int32_t rc;
	while (enviado) {
		rc = send(descriptor, paquete, sizeof(paquete), 0);
		if (rc < 0) {
			perror("send(), no se pudo enviar el mensaje");
		} else {
			enviado++;
			printf("mensaje enviado\n");
		}
	}
}

void ponermeALaEscucha(uint32_t descriptor) {
	int32_t rc = listen(descriptor, 1);
	if (rc < 0) {
		perror("listen");
	}
	return;
}

char* recibirPaquete(uint32_t descriptor, uint64_t longitud) {
	char* paquete = (char*) malloc(longitud);
	if (recv(descriptor, paquete, longitud, 0) < 0) {
		perror("recv");
	}
	return paquete;
}

int8_t controlarHandShake(char* HS) {
	if ((HS[0] == 0) && (HS[1] == 0) && (HS[2] == 0))
		return 0;
	else
		return -1;
}
convertirAServidor(int32_t** descriptor, char* IP, char* puerto) {
	cerrarConexionSocket(descriptor);
	descriptor = crearServidor(IP, puerto);
}

void crearPaqueteTiempo(uint64_t tiempo, char** respuesta) {

	respuesta[0] = 0;
	respuesta[1] = 0;
	respuesta[2] = 8;
	int8_t i;
	for (i = 3; i < 11; i++) {
		respuesta[i] = div(tiempo, potencia(2, 10 - i)).quot;
		tiempo -= div(tiempo, potencia(2, 10 - i)).quot;
	};
}
